package com.lpz.factory;

import sun.misc.ExtensionInstallationException;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 一个创建Bean对象的工厂
 * Bean:可重用组件，那么在实际开发中，javabean比实体类的范围大很多。
 * 它就是创建我们的service和dao对象
 *  1、需要一个配置文件来配置我们的service和dao
 *      配置的内容：唯一标识=全限定类名（key=value的格式）
 *  2、通过读取配置文件中配置的内容，反射创建对象。
 *  配置文件可以是xml或者是properties
 *          properties中的是指向servicce或者dao的全限定类名
 *
 *
 */
public class BeanFactory {
    //1定义一个properties对象，解析properties文件
    private static Properties props;
    //经过分析之后，需要对此进行升级。定一个map，用于存放我们要创建的对象，我们把它称为容器。
    private static Map<String,Object> beans;
    //2使用静态代码块为Properties对象赋值
    static {
        try {
            //2。1实例化对象
            props=new Properties();
            //2.2获取Properties文件的流对象
            InputStream in=BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            //2.3 实例化容器
            beans=new HashMap<String, Object>();
            //取出配置文件中有的k
            Enumeration keys=props.keys();
            //遍历枚举
            while (keys.hasMoreElements()){
                //取出每个key
                String key=keys.nextElement().toString();
                //根据key获取value
                String beanPath=props.getProperty(key);
                //反射创建对象
                Object value=Class.forName(beanPath).newInstance();
                //把key和value存储容器
                beans.put(key,value);
            }
        } catch (Exception e) {
           throw  new ExceptionInInitializerError("初始化properties失败");
        }
    }
    //3建立方法获取service和dao的对象
    /***
     * 改造升级之后的方法，就变成了单例
     * @param benaName
     * @return
     */
    public static Object getBean(String benaName){
      return beans.get(benaName);//就可以得到benavalue
    }

    //3建立方法获取service和dao的对象
    /***
     * 根据bean的名称获取bena的对象，这个是多例的。
     * @param benaName
     * @return

    public static Object getBean(String benaName){
        Object bena=null;
        try {
            //输出的是解耦操作之后，给传参数中properties对应的全限定类名
            String benaPath = props.getProperty(benaName);
            //用newInstance进行对象的实例化。
            /**
             * newInstance()和new()区别：
             * 　　1、两者创建对象的方式不同，前者是实用类的加载机制，后者则是直接创建一个类：
             * 　　2、newInstance创建类是这个类必须已经加载过且已经连接，new创建类是则不需要这个类加载过
             * 　　3、newInstance: 弱类型(GC是回收对象的限制条件很低，容易被回收)、低效率、只能调用无参构造，new 强类型（GC不会自动回收，只有所有的指向对象的引用被移除是才会被回收，若对象生命周期已经结束，但引用没有被移除，经常会出现内存溢出）

            bena = Class.forName(benaPath).newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        return  bena;
    }*/
}
